Skip to content

Dev#378

Open
TatevikGr wants to merge 12 commits intomainfrom
dev
Open

Dev#378
TatevikGr wants to merge 12 commits intomainfrom
dev

Conversation

@TatevikGr
Copy link
Contributor

@coderabbitai summary

Thanks for contributing to phpList!

TatevikGr and others added 2 commits February 9, 2026 13:03
* UserPersonalizer in CampaignProcessorMessageHandler

* HtmlToText

* MessageDataLoader

* TextParser

* RemotePageFetcher

* Use repo methods

* Use MessagePrecacheDto

* Refactor

* Todo

* SystemMailConstructor

* EmailBuilder

* InjectedByHeaderSubscriber

* TemplateImageManager

* ExternalImageCacher

* TemplateImageEmbedder

* Mailer

* RemotePageFetcherTest

* TextParserTest

* MessageDataLoaderTest

* MessageDataLoaderTest

* Test fix

* Fix: phpmd

* Fix: phpcs

* After review 0

* After review 1

* Add tests

* EmailBuilderTest

* update coderabbit.yaml

* Add tests

* MailSizeChecker

* Feat/email building with attachments (#375)

New Features
    PDF generation for messages, per-subscriber remote-content fetching, tracking-pixel user tracking, and richer attachment handling with downloadable copies.

Improvements
    Unified email builder flow with consistent composition and multi-format output (HTML/Text/PDF); expanded, context-aware placeholder personalization (many URL/list resolvers); improved remote-content precaching and output formatting; new configurable parameters and translations.

---------

Co-authored-by: Tatevik <tatevikg1@gmail.com>

* Feat: email forwarding (#377)

-  Message forwarding: send campaigns to friends (optional personal note), per-user limits, admin notifications on success/failure, and forwarding statistics; forwarded messages prefixed "Fwd".
-  Admin-copy emails: configurable toggle to send admin copies and select recipients.

---------

Co-authored-by: Tatevik <tatevikg1@gmail.com>

* Cutoff from forward_email_period config

* ForwardingResult

* Remove MessageFormat consts

* Testing bundle

* After review 3

* MessageDataLoader types

* Fix HTMLPurifier_Config

---------

Co-authored-by: Tatevik <tatevikg1@gmail.com>
New Features

    Attachment download service that validates access, resolves files, detects MIME types, and returns downloadable content.
    Lightweight downloadable attachment DTO and a new exception for missing attachment files.
    Public constant to mark forwarded attachments.

Bug Fixes

    Attachment download links now use a path-based format with encoded UID.
@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Important

Review skipped

Too many files!

This PR contains 265 files, which is 115 over the limit of 150.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6a1ba0ee-d7d6-4c23-a139-1aea9270690e

📥 Commits

Reviewing files that changed from the base of the PR and between 83431b1 and fa0af38.

📒 Files selected for processing (265)
  • .coderabbit.yaml
  • composer.json
  • config/PHPMD/rules.xml
  • config/PhpCodeSniffer/ruleset.xml
  • config/parameters.yml.dist
  • config/services.yml
  • config/services/builders.yml
  • config/services/managers.yml
  • config/services/messenger.yml
  • config/services/parameters.yml
  • config/services/providers.yml
  • config/services/repositories.yml
  • config/services/resolvers.yml
  • config/services/services.yml
  • phpunit.xml.dist
  • resources/translations/messages.en.xlf
  • src/Bounce/Service/LockService.php
  • src/Composer/ModuleFinder.php
  • src/Core/Version.php
  • src/DependencyInjection/PhpListCoreExtension.php
  • src/Domain/Analytics/Model/UserMessageView.php
  • src/Domain/Analytics/Service/AnalyticsService.php
  • src/Domain/Analytics/Service/LinkTrackService.php
  • src/Domain/Analytics/Service/UserMessageService.php
  • src/Domain/Common/ExternalImageService.php
  • src/Domain/Common/FileHelper.php
  • src/Domain/Common/Html2Text.php
  • src/Domain/Common/HtmlUrlRewriter.php
  • src/Domain/Common/IspRestrictionsProvider.php
  • src/Domain/Common/Model/ContentTransferEncoding.php
  • src/Domain/Common/Model/PaginatedResult.php
  • src/Domain/Common/OnceCacheGuard.php
  • src/Domain/Common/PdfGenerator.php
  • src/Domain/Common/RemotePageFetcher.php
  • src/Domain/Common/Repository/CursorPaginationTrait.php
  • src/Domain/Common/Repository/Interfaces/PaginatableRepositoryInterface.php
  • src/Domain/Common/TextParser.php
  • src/Domain/Configuration/Model/ConfigOption.php
  • src/Domain/Configuration/Model/Dto/PlaceholderContext.php
  • src/Domain/Configuration/Model/OutputFormat.php
  • src/Domain/Configuration/Repository/EventLogRepository.php
  • src/Domain/Configuration/Repository/UrlCacheRepository.php
  • src/Domain/Configuration/Service/LegacyUrlBuilder.php
  • src/Domain/Configuration/Service/Manager/EventLogManager.php
  • src/Domain/Configuration/Service/MessagePlaceholderProcessor.php
  • src/Domain/Configuration/Service/Placeholder/BlacklistUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/BlacklistValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ConfirmationUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ContactUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ContactValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/FooterValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ForwardMessageIdValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ForwardUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ForwardValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/JumpoffUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/JumpoffValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/ListsValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/PatternValueResolverInterface.php
  • src/Domain/Configuration/Service/Placeholder/PlaceholderValueResolverInterface.php
  • src/Domain/Configuration/Service/Placeholder/PreferencesUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/PreferencesValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/SignatureValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/SubscribeUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/SubscribeValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/SupportingPlaceholderResolverInterface.php
  • src/Domain/Configuration/Service/Placeholder/UnsubscribeUrlValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/UnsubscribeValueResolver.php
  • src/Domain/Configuration/Service/Placeholder/UserDataSupportingResolver.php
  • src/Domain/Configuration/Service/Placeholder/UserTrackValueResolver.php
  • src/Domain/Configuration/Service/PlaceholderResolver.php
  • src/Domain/Configuration/Service/Provider/ConfigProvider.php
  • src/Domain/Configuration/Service/Provider/DefaultConfigProvider.php
  • src/Domain/Configuration/Service/UserPersonalizer.php
  • src/Domain/Identity/Command/ImportDefaultsCommand.php
  • src/Domain/Identity/Model/AdminAttributeDefinition.php
  • src/Domain/Identity/Model/Administrator.php
  • src/Domain/Identity/Model/Dto/AdminAttributeDefinitionDto.php
  • src/Domain/Identity/Model/Dto/CreateAdministratorDto.php
  • src/Domain/Identity/Repository/AdminAttributeDefinitionRepository.php
  • src/Domain/Identity/Repository/AdminAttributeValueRepository.php
  • src/Domain/Identity/Repository/AdministratorRepository.php
  • src/Domain/Identity/Service/AdminCopyEmailSender.php
  • src/Domain/Identity/Service/AdminNotifier.php
  • src/Domain/Identity/Service/Manager/AdminAttributeDefinitionManager.php
  • src/Domain/Identity/Service/Manager/AdminAttributeManager.php
  • src/Domain/Identity/Service/Manager/AdministratorManager.php
  • src/Domain/Identity/Service/Manager/PasswordManager.php
  • src/Domain/Identity/Service/Manager/SessionManager.php
  • src/Domain/Messaging/Command/ProcessQueueCommand.php
  • src/Domain/Messaging/EventSubscriber/InjectedByHeaderSubscriber.php
  • src/Domain/Messaging/Exception/AttachmentCopyException.php
  • src/Domain/Messaging/Exception/AttachmentException.php
  • src/Domain/Messaging/Exception/AttachmentFileNotFoundException.php
  • src/Domain/Messaging/Exception/DevEmailNotConfiguredException.php
  • src/Domain/Messaging/Exception/EmailBlacklistedException.php
  • src/Domain/Messaging/Exception/ForwardLimitExceededException.php
  • src/Domain/Messaging/Exception/InvalidRecipientOrSubjectException.php
  • src/Domain/Messaging/Exception/MessageCacheMissingException.php
  • src/Domain/Messaging/Exception/MessageNotReceivedException.php
  • src/Domain/Messaging/Exception/RemotePageFetchException.php
  • src/Domain/Messaging/Exception/SubscriberNotFoundException.php
  • src/Domain/Messaging/Message/SubscriberConfirmationMessage.php
  • src/Domain/Messaging/Message/SubscriptionConfirmationMessage.php
  • src/Domain/Messaging/MessageHandler/AsyncEmailMessageHandler.php
  • src/Domain/Messaging/MessageHandler/CampaignProcessorMessageHandler.php
  • src/Domain/Messaging/MessageHandler/PasswordResetMessageHandler.php
  • src/Domain/Messaging/MessageHandler/SubscriberConfirmationMessageHandler.php
  • src/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandler.php
  • src/Domain/Messaging/Model/Attachment.php
  • src/Domain/Messaging/Model/Dto/CreateTemplateDto.php
  • src/Domain/Messaging/Model/Dto/DownloadableAttachment.php
  • src/Domain/Messaging/Model/Dto/ForwardingRecipientResult.php
  • src/Domain/Messaging/Model/Dto/ForwardingResult.php
  • src/Domain/Messaging/Model/Dto/MessageForwardDto.php
  • src/Domain/Messaging/Model/Dto/MessagePrecacheDto.php
  • src/Domain/Messaging/Model/Dto/UpdateTemplateDto.php
  • src/Domain/Messaging/Model/Message.php
  • src/Domain/Messaging/Model/Message/MessageFormat.php
  • src/Domain/Messaging/Model/Message/MessageMetadata.php
  • src/Domain/Messaging/Model/UserMessage.php
  • src/Domain/Messaging/Repository/AttachmentRepository.php
  • src/Domain/Messaging/Repository/MessageDataRepository.php
  • src/Domain/Messaging/Repository/MessageRepository.php
  • src/Domain/Messaging/Repository/TemplateImageRepository.php
  • src/Domain/Messaging/Repository/TemplateRepository.php
  • src/Domain/Messaging/Repository/UserMessageForwardRepository.php
  • src/Domain/Messaging/Repository/UserMessageRepository.php
  • src/Domain/Messaging/Service/AttachmentAdder.php
  • src/Domain/Messaging/Service/AttachmentDownloadService.php
  • src/Domain/Messaging/Service/Builder/BaseEmailBuilder.php
  • src/Domain/Messaging/Service/Builder/EmailBuilder.php
  • src/Domain/Messaging/Service/Builder/ForwardEmailBuilder.php
  • src/Domain/Messaging/Service/Builder/HttpReceivedStampBuilder.php
  • src/Domain/Messaging/Service/Builder/MessageFormatBuilder.php
  • src/Domain/Messaging/Service/Builder/SystemEmailBuilder.php
  • src/Domain/Messaging/Service/Constructor/CampaignMailContentBuilder.php
  • src/Domain/Messaging/Service/Constructor/SystemMailContentBuilder.php
  • src/Domain/Messaging/Service/EmailService.php
  • src/Domain/Messaging/Service/ForwardContentService.php
  • src/Domain/Messaging/Service/ForwardDeliveryService.php
  • src/Domain/Messaging/Service/ForwardingGuard.php
  • src/Domain/Messaging/Service/ForwardingStatsService.php
  • src/Domain/Messaging/Service/MailSizeChecker.php
  • src/Domain/Messaging/Service/Manager/TemplateImageManager.php
  • src/Domain/Messaging/Service/Manager/UserMessageForwardManager.php
  • src/Domain/Messaging/Service/MessageDataLoader.php
  • src/Domain/Messaging/Service/MessageForwardService.php
  • src/Domain/Messaging/Service/MessagePrecacheService.php
  • src/Domain/Messaging/Service/MessageProcessingPreparator.php
  • src/Domain/Messaging/Service/RateLimitedCampaignMailer.php
  • src/Domain/Messaging/Service/TemplateImageEmbedder.php
  • src/Domain/Subscription/Exception/AttributeNotAllowedException.php
  • src/Domain/Subscription/Model/Dto/AttributeDefinitionDto.php
  • src/Domain/Subscription/Model/Dto/CreateSubscriberListDto.php
  • src/Domain/Subscription/Model/Dto/SubscriberImportOptions.php
  • src/Domain/Subscription/Model/Filter/SubscriberFilter.php
  • src/Domain/Subscription/Model/Subscriber.php
  • src/Domain/Subscription/Model/SubscriberAttributeDefinition.php
  • src/Domain/Subscription/Repository/SubscriberAttributeDefinitionRepository.php
  • src/Domain/Subscription/Repository/SubscriberAttributeValueRepository.php
  • src/Domain/Subscription/Repository/SubscriberHistoryRepository.php
  • src/Domain/Subscription/Repository/SubscriberListRepository.php
  • src/Domain/Subscription/Repository/SubscriberRepository.php
  • src/Domain/Subscription/Repository/UserBlacklistRepository.php
  • src/Domain/Subscription/Service/Manager/AttributeDefinitionManager.php
  • src/Domain/Subscription/Service/Manager/SubscribePageManager.php
  • src/Domain/Subscription/Service/Manager/SubscriberAttributeManager.php
  • src/Domain/Subscription/Service/Manager/SubscriberHistoryManager.php
  • src/Domain/Subscription/Service/Manager/SubscriberListManager.php
  • src/Domain/Subscription/Service/Manager/SubscriberManager.php
  • src/Domain/Subscription/Service/SubscriberCsvExporter.php
  • src/Domain/Subscription/Service/SubscriberCsvImporter.php
  • src/Migrations/Version20260204094237.php
  • src/PhpListCoreBundle.php
  • tests/Integration/Domain/Messaging/Fixtures/MessageFixture.php
  • tests/Integration/Domain/Messaging/Repository/MessageRepositoryTest.php
  • tests/Integration/Domain/Subscription/Fixtures/SubscriberFixture.php
  • tests/Integration/Domain/Subscription/Repository/SubscriberRepositoryTest.php
  • tests/Integration/Domain/Subscription/Service/SubscriberCsvExportManagerTest.php
  • tests/Integration/Domain/Subscription/Service/SubscriberCsvImportManagerTest.php
  • tests/Integration/Domain/Subscription/Service/SubscriberDeletionServiceTest.php
  • tests/Unit/Bounce/Service/WebklexImapClientFactoryTest.php
  • tests/Unit/Composer/ModuleFinderTest.php
  • tests/Unit/Domain/Analytics/Service/AnalyticsServiceTest.php
  • tests/Unit/Domain/Analytics/Service/LinkTrackServiceTest.php
  • tests/Unit/Domain/Analytics/Service/UserMessageServiceTest.php
  • tests/Unit/Domain/Common/FileHelperTest.php
  • tests/Unit/Domain/Common/HtmlUrlRewriterTest.php
  • tests/Unit/Domain/Common/OnceCacheGuardTest.php
  • tests/Unit/Domain/Common/PdfGeneratorTest.php
  • tests/Unit/Domain/Common/RemotePageFetcherTest.php
  • tests/Unit/Domain/Common/Repository/CursorPaginationTraitTest.php
  • tests/Unit/Domain/Common/TextParserTest.php
  • tests/Unit/Domain/Configuration/Service/Manager/EventLogManagerTest.php
  • tests/Unit/Domain/Configuration/Service/MessagePlaceholderProcessorTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/BlacklistUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/BlacklistValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ConfirmationUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ContactUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ContactValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/FooterValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ForwardMessageIdValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ForwardUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ForwardValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/JumpoffUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/JumpoffValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/ListsValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/PreferencesUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/PreferencesValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/SignatureValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/SubscribeUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/SubscribeValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/UnsubscribeUrlValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/UnsubscribeValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/UserDataSupportingResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Placeholder/UserTrackValueResolverTest.php
  • tests/Unit/Domain/Configuration/Service/PlaceholderResolverTest.php
  • tests/Unit/Domain/Configuration/Service/Provider/ConfigProviderTest.php
  • tests/Unit/Domain/Configuration/Service/Provider/DefaultConfigProviderTest.php
  • tests/Unit/Domain/Configuration/Service/UserPersonalizerTest.php
  • tests/Unit/Domain/Identity/Service/AdminAttributeDefinitionManagerTest.php
  • tests/Unit/Domain/Identity/Service/AdminAttributeManagerTest.php
  • tests/Unit/Domain/Identity/Service/AdminCopyEmailSenderTest.php
  • tests/Unit/Domain/Identity/Service/AdminNotifierTest.php
  • tests/Unit/Domain/Identity/Service/AdministratorManagerTest.php
  • tests/Unit/Domain/Identity/Service/PasswordManagerTest.php
  • tests/Unit/Domain/Identity/Service/SessionManagerTest.php
  • tests/Unit/Domain/Messaging/EventSubscriber/InjectedByHeaderSubscriberTest.php
  • tests/Unit/Domain/Messaging/MessageHandler/CampaignProcessorMessageHandlerTest.php
  • tests/Unit/Domain/Messaging/MessageHandler/SubscriptionConfirmationMessageHandlerTest.php
  • tests/Unit/Domain/Messaging/Model/MessageTest.php
  • tests/Unit/Domain/Messaging/Model/SubscriberListTest.php
  • tests/Unit/Domain/Messaging/Service/AttachmentAdderTest.php
  • tests/Unit/Domain/Messaging/Service/AttachmentDownloadServiceTest.php
  • tests/Unit/Domain/Messaging/Service/Builder/EmailBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/Builder/ForwardEmailBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/Builder/HttpReceivedStampBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/Builder/MessageFormatBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/Builder/SystemEmailBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/Constructor/CampaignMailContentBuilderTest.php
  • tests/Unit/Domain/Messaging/Service/ForwardContentServiceTest.php
  • tests/Unit/Domain/Messaging/Service/ForwardDeliveryServiceTest.php
  • tests/Unit/Domain/Messaging/Service/ForwardingGuardTest.php
  • tests/Unit/Domain/Messaging/Service/ForwardingStatsServiceTest.php
  • tests/Unit/Domain/Messaging/Service/MailSizeCheckerTest.php
  • tests/Unit/Domain/Messaging/Service/Manager/BounceManagerTest.php
  • tests/Unit/Domain/Messaging/Service/Manager/TemplateImageManagerTest.php
  • tests/Unit/Domain/Messaging/Service/Manager/UserMessageForwardManagerTest.php
  • tests/Unit/Domain/Messaging/Service/MessageDataLoaderTest.php
  • tests/Unit/Domain/Messaging/Service/MessageForwardServiceTest.php
  • tests/Unit/Domain/Messaging/Service/MessageProcessingPreparatorTest.php
  • tests/Unit/Domain/Messaging/Service/RateLimitedCampaignMailerTest.php
  • tests/Unit/Domain/Messaging/Service/SystemMailConstructorTest.php
  • tests/Unit/Domain/Messaging/Service/TemplateImageEmbedderTest.php
  • tests/Unit/Domain/Subscription/Model/SubscriberTest.php
  • tests/Unit/Domain/Subscription/Model/SubscriptionTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriberAttributeManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriberBlacklistManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriberHistoryManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriberListManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriberManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Manager/SubscriptionManagerTest.php
  • tests/Unit/Domain/Subscription/Service/Provider/CheckboxGroupValueProviderTest.php
  • tests/Unit/Domain/Subscription/Service/Provider/SubscriberAttributeChangeSetProviderTest.php
  • tests/Unit/Domain/Subscription/Service/SubscriberCsvExporterTest.php

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes.

Add @coderabbitai placeholder anywhere in the title of your PR and CodeRabbit will replace it with a title based on the changes in the PR. You can change the placeholder by changing the reviews.auto_title_placeholder setting.

@TatevikGr TatevikGr changed the title Feat: message sending-forwarding (#374) Dev Feb 11, 2026
TatevikGr and others added 7 commits February 13, 2026 12:24
New Features

    Message view tracking: records when subscribers view messages and captures metadata (IP, User-Agent, referer).

Enhancements

    Quick actions to mark messages as viewed and to check viewed status.
    Message view counters now increment when viewed.

Refactor

    Repository lookup renamed for consistency and callers updated.

Chores

    Switched REST API parameter to a base URL and updated tracking image path.
    Refactor
        Recipient addresses are now passed explicitly throughout the email pipeline for clearer, more reliable message construction and handling.
        Subscriber creation now requires an email at instantiation, enforcing consistent initialization.
    Bug Fixes
        Admin notification filtering relaxed so system notifications are handled more consistently even when recipient info is missing.
@TatevikGr
Copy link
Contributor Author

@coderabbitai please add a summary of this pull request:

  • key changes

@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch PR details
gh pr view 378 --repo phpList/core --json title,body,files,additions,deletions,commits

# List changed files
gh pr diff 378 --repo phpList/core --name-only

Length of output: 35008


@TatevikGr Here's a summary of the key changes in this PR:


🗂️ PR Summary — Key Changes

📧 Email Building Pipeline (Refactor + New Features)

  • Introduced a unified email builder hierarchy: BaseEmailBuilder, EmailBuilder, ForwardEmailBuilder, and SystemEmailBuilder, alongside CampaignMailContentBuilder and SystemMailContentBuilder for consistent HTML/Text/PDF output composition.
  • Added InjectedByHeaderSubscriber and HttpReceivedStampBuilder for richer email header management.
  • Added MailSizeChecker to validate email size before dispatch.

📤 Message Forwarding (#374, #377)

  • New MessageForwardService, ForwardDeliveryService, ForwardContentService, ForwardingGuard, and ForwardingStatsService to support sending campaigns to friends with optional personal notes.
  • Per-user forwarding limits (ForwardLimitExceededException), admin notifications on success/failure, and forwarded messages are prefixed with "Fwd".
  • UserMessageForwardRepository and UserMessageForwardManager added for persistence.

📎 Attachment Download Service (#379)

  • New AttachmentDownloadService that validates access, resolves files, detects MIME types, and returns downloadable content.
  • Added DownloadableAttachment DTO and AttachmentFileNotFoundException.
  • Attachment download links now use path-based URLs with encoded UIDs.

👁️ Message Open Tracking (#380)

  • New UserMessageService to record when subscribers view messages, capturing metadata (IP, User-Agent, referrer).
  • View counters now increment on open; quick-action methods added to mark messages as viewed and check viewed status.
  • REST API switched to a base URL; tracking image path updated.

🔤 Placeholder System (Major Expansion)

  • New MessagePlaceholderProcessor and a full suite of per-context value resolvers under Service/Placeholder/, covering: unsubscribe, subscribe, forward, blacklist, confirmation, contact, footer, jumpoff, preferences, signature, lists, and user-tracking URLs.
  • PlaceholderContext DTO introduced for richer, context-aware personalization.
  • PlaceholderResolver refactored to support the new resolver interfaces.

📄 PDF & Remote Content

  • PdfGenerator added for per-message PDF generation.
  • RemotePageFetcher added for per-subscriber remote-content fetching with caching (OnceCacheGuard).
  • ExternalImageService and HtmlUrlRewriter added for external image handling and URL rewriting.

🔔 Admin Copy Emails & Notifications

  • New AdminCopyEmailSender and AdminNotifier services; configurable toggle to send admin copies and select recipients.

📋 Subscriber Filtering & Pagination

  • SubscriberFilter expanded with new filter options.
  • getFilteredAfterId query fixed from innerJoinleftJoin.
  • New PaginatedResult model; CursorPaginationTrait and PaginatableRepositoryInterface improved.
  • Fixed subscriber property name bug in query builder condition.
  • Added getSubscriberDetails method.

🔧 Refactors & Fixes

  • MessagePrecacheDto refactored — recipient to address removed from DTO, now passed explicitly through the pipeline.
  • Subscriber model now requires email at instantiation.
  • Admin manager classes renamed for consistency (Manager/ namespace).
  • HTMLPurifier_Config fix applied.
  • MessageFormat constants removed.

📦 Dependencies & Configuration

  • Guzzle upgraded.
  • 67 new configurable parameters added to parameters.yml.dist.
  • 88 new translation strings added to messages.en.xlf.
  • PhpListCoreExtension DI extension class added.
  • .coderabbit.yaml updated.
  • DB migration added: Version20260204094237.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants